'''
copyright: Copyright (C) 2015-2024, Wazuh Inc.

           Created by Wazuh, Inc. <info@wazuh.com>.

           This program is free software; you can redistribute it and/or modify it under the terms of GPLv2

type: integration

brief: Wazuh is able to detect vulnerabilities in the applications installed in agents using the Vulnerability Detector
       module. This software audit is performed through the integration of vulnerability feeds indexed by Redhat,
       Canonical, Debian, Amazon Linux and NVD Database.

components:
    - vulnerability_detector

suite: feeds

targets:
    - manager

daemons:
    - wazuh-modulesd
    - wazuh-db

os_platform:
    - linux

os_version:
    - Arch Linux
    - Amazon Linux 2
    - Amazon Linux 1
    - CentOS 8
    - CentOS 7
    - Debian Buster
    - Red Hat 8
    - Ubuntu Focal
    - Ubuntu Bionic

references:
    - https://documentation.wazuh.com/current/user-manual/capabilities/vulnerability-detection/index.html

tags:
    - vulnerability_detector
    - cpe_helper
'''
import json
import pytest
from pathlib import Path

from wazuh_testing import FEEDS_PATH
from wazuh_testing.constants.daemons import ANALYSISD_DAEMON, MODULES_DAEMON, SYSCHECK_DAEMON
from wazuh_testing.constants.paths.logs import WAZUH_LOG_PATH
from wazuh_testing.utils.configuration import (load_configuration_template, get_test_cases_data,
                                               update_configuration_template)
from wazuh_testing.utils.callbacks import generate_callback
from wazuh_testing.modules.modulesd.vulnerability_detector import patterns as cb
from wazuh_testing.modules import vulnerability_detector as vd
from wazuh_testing.modules.modulesd.configuration import MODULESD_DEBUG
from wazuh_testing.modules.monitord.configuration import MONITORD_ROTATE_LOG
from wazuh_testing.utils.mocking import VULNERABLE_PACKAGES
from wazuh_testing.tools.monitors.file_monitor import FileMonitor
from . import TEST_CASES_PATH, CONFIGURATIONS_PATH


pytest.skip("The tests will be deprecated, they test the old Vulnerability Detector.", allow_module_level=True)

local_internal_options = {MODULESD_DEBUG: '2', MONITORD_ROTATE_LOG: '0'}
pytestmark = [pytest.mark.server]

# Configuration and cases data
configurations_path = Path(CONFIGURATIONS_PATH, 'configuration_cpe_indexing.yaml')
cases_path = Path(TEST_CASES_PATH, 'cases_cpe_indexing_wrong_values.yaml')

# CPE indexing packages test configurations (t2)
configuration_parameters, configuration_metadata, test_case_ids = get_test_cases_data(cases_path)
configurations = load_configuration_template(configurations_path, configuration_parameters,
                                             configuration_metadata)
systems = [metadata['system'] for metadata in configuration_metadata]

# Set offline custom feeds configuration
custom_nvd_json_feed_path = str(Path(FEEDS_PATH, 'nvd', vd.CUSTOM_NVD_FEED))
configurations = update_configuration_template(configurations, ['CUSTOM_NVD_JSON_PATH'], [custom_nvd_json_feed_path])

# Global vars
agent_packages = [VULNERABLE_PACKAGES for metadata in configuration_metadata]
daemons_handler_configuration = {'daemons': [ANALYSISD_DAEMON, MODULES_DAEMON, SYSCHECK_DAEMON]}


@pytest.mark.tier(level=2)
@pytest.mark.parametrize('test_configuration, test_metadata, agent_system, agent_packages',
                         zip(configurations, configuration_metadata, systems, agent_packages),
                         ids=test_case_ids)
def test_cpe_indexing_wrong_values(test_configuration, test_metadata, agent_system, agent_packages,
                                   set_wazuh_configuration, configure_local_internal_options,
                                   truncate_monitored_files, clean_cve_tables, prepare_environment,
                                   daemons_handler):
    '''
    description: Check for invalid values in the cpe_helper.json file.

    test_phases:
    - setup:
        - Load Wazuh light configuration, with custom feeds.
        - Apply ossec.conf configuration changes according to the configuration template and use case.
        - Apply custom settings in local_internal_options.conf.
        - Mock an agent with Windows system and vulnerable packages.
        - Backup the original cpe_helper.json and copy a custom CPE helper with new tags and values.
        - Truncate wazuh logs.
        - Restart wazuh-modulesd daemon to apply configuration changes.
    - test:
        - Check in the log for specific information.
    - teardown:
        - Truncate wazuh logs.
        - Restore initial configuration, both ossec.conf and local_internal_options.conf.
        - Restore the original cpe_helper.json

    wazuh_min_version: 4.5.0

    tier: 2

    parameters:
        - test_configuration:
            type: dict
            brief: Wazuh configuration data. Needed for set_wazuh_configuration fixture.
        - test_metadata:
            type: dict
            brief: Wazuh configuration metadata.
        - agent_system:
            type: str
            brief: System to set to the mocked agent.
        - agent_packages
            type: list
            brief: List of vulnerable packages.
        - set_wazuh_configuration:
            type: fixture
            brief: Set the wazuh configuration according to the configuration data.
        - configure_local_internal_options:
            type: fixture
            brief: Set local_internal_options configuration.
        - truncate_monitored_files:
            type: fixture
            brief: Truncate all the log files and json alerts files before and after the test execution.
        - clean_cve_tables:
            type: fixture
            brief: Clean all CVE tables.
        - prepare_environment:
            type: fixture
            brief: Setup the initial test state.
        - daemons_handler:
            type: fixture
            brief: Restart the wazuh-modulesd daemon.

    assertions:
        - Check for a specific log according to the stage.

    input_description:
        - The `configuration_cpe_indexing_wrong_values.yaml` file provides the module configuration for this test.
        - The `cases_cpe_indexing_wrong_values.yaml` file provides the test cases.

    expected_output:
        - fr"WARNING: .* Invalid tag found when parsing the CPE dictionary: '{field}'
        - r"The CPE .*a:{package_vendor}:{package_name}.* from the agent '{agent_id}' was indexed"
        - r"ERROR: .* Invalid format version for the CPE helper: .*"
    '''
    file_monitor = FileMonitor(WAZUH_LOG_PATH)
    expected_result = test_metadata['expected_result']

    if expected_result == 'invalid_tag':
        file_monitor.start(timeout=30, callback=generate_callback(regex=cb.CPE_INVALID_TAG,
                                                                  replacement={'field': test_metadata['wrong_field']}))
        assert file_monitor.callback_result is not None, f"The expected '{cb.CPE_INVALID_TAG}' event was not found."

    elif expected_result == 'package_indexed':
        for package in agent_packages[0:1]:
            callback = generate_callback(regex=cb.CPE_PACKAGE_INDEXED,
                                         replacement={'package_name': package['name'],
                                                      'package_vendor': package['vendor'],
                                                      'agent_id': prepare_environment})
            file_monitor.start(timeout=30, callback=callback)
            assert file_monitor.callback_result is not None, cb.ERR_MSG_PACKAGE_NOT_INDEXED

    elif expected_result == 'invalid_format':
        file_monitor.start(timeout=30, callback=generate_callback(regex=cb.CPE_INVALID_FORMAT_VERSION))
        assert file_monitor.callback_result is not None, f"Expected '{cb.CPE_INVALID_FORMAT_VERSION}' event not found."

    elif expected_result == 'package_not_indexed':
        for package in agent_packages[0:1]:
            # Check that packages were not indexed due to the wrong values.
            file_monitor.start(timeout=20, callback=generate_callback(regex=cb.CPE_PACKAGE_INDEXED,
                                                                      replacement={'package_name': package['name'],
                                                                                   'package_vendor': package['vendor'],
                                                                                   'agent_id': prepare_environment}))
            assert file_monitor.callback_result is None, f"Package {package['name']} was indexed, when it should not."
